﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using ProxyHero.Common;
using System.Threading;
using ProxyHero.HttpUility;
using ProxyHero.Entity;
using System.IO;
using System.Diagnostics;

namespace ProxyHero.TabPages
{
    public partial class frmProxy : Form
    {
        #region Variable
        delegate void DelegateEnable();
        delegate void DelegateVoid();
        delegate void DelegateTestAll(object pse);
        delegate void DelegateAddToAvaliableProxy(object Ip, object Port, object Spped);
        string strIP;
        string strPort;

        Thread threadGetProxyList = null;
        Thread threadTest = null;
        Thread[] theads = null;

        bool[] testAll = null;

        ProxyHelper proxyHelper = new ProxyHelper();
        /// <summary>
        /// 测试耗时
        /// </summary>
        Stopwatch swTestAll = new Stopwatch();
        #endregion

        #region Constructors
        public frmProxy()
        {
            InitializeComponent();
        }
        #endregion

        #region Operation 
        private void tsmiTest_Click(object sender, EventArgs e)
        {
            try
            {
                if (string.IsNullOrEmpty(this.strIP) ||
                     string.IsNullOrEmpty(this.strPort))
                {
                    Config.MainForm.SetStatusText("请先设置代理服务器，再验证！");
                    return;
                }

                DelegateVoid delegateTest = new DelegateVoid(this.Test);
                threadTest = new Thread(new ThreadStart(delegateTest));
                threadTest.Start();
            }
            catch (Exception ex)
            {
                MsgBox.ShowExceptionMessage(ex);
            }
        }

        private void dgvProxyList_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            try
            {
                if (e.RowIndex > -1)
                {
                    strIP = this.dgvProxyList.Rows[e.RowIndex].Cells[0].Value as string;
                    strPort = this.dgvProxyList.Rows[e.RowIndex].Cells[1].Value as string;

                    if (e.Button == MouseButtons.Right)
                    {
                        this.dgvProxyList.CurrentCell = this.dgvProxyList.Rows[e.RowIndex].Cells[e.ColumnIndex];
                        this.contextMenuStrip1.Show(Control.MousePosition);
                    }
                }
            }
            catch (Exception ex)
            {
                MsgBox.ShowExceptionMessage(ex);
            }
        }

        private void tsmiCopy_Click(object sender, EventArgs e)
        {
            try
            {
                string strProxyServer = GetProxyInfo();
                Clipboard.SetText(strProxyServer);
                Config.MainForm.SetStatusText("已成功复制代理:" + strProxyServer);
            }
            catch (Exception ex)
            {
                MsgBox.ShowExceptionMessage(ex);
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            try
            {
                bool testOk = true;
                int intOk = 0;
                for (int i = 0; i < Config.ProxyData.Rows.Count; i++)
                {
                    testOk &= testAll[i];
                    if (testAll[i])
                    {
                        intOk += 1;
                    }
                }

                StringBuilder strInfo = new StringBuilder();
                strInfo.Append("正在验证");
                strInfo.Append(intOk);
                strInfo.Append("/");
                strInfo.Append(Config.ProxyData.Rows.Count);
                strInfo.Append("...");

                Config.MainForm.SetStatusText(strInfo.ToString());
                if (testOk)
                {
                    swTestAll.Stop();
                     StringBuilder sb = new StringBuilder();
                     if (swTestAll.Elapsed.Days > 0)
                         sb.Append(swTestAll.Elapsed.Days + "天");
                     if (swTestAll.Elapsed.Hours > 0)
                         sb.Append(swTestAll.Elapsed.Hours + "小时");
                     if (swTestAll.Elapsed.Minutes > 0)
                         sb.Append(swTestAll.Elapsed.Minutes + "分");
                     sb.Append(swTestAll.Elapsed.Seconds + "秒");

                    this.tsmiTest.Enabled = true;
                    this.tsmiDelete.Enabled = true;
                    this.tsmiClear.Enabled = true;
                    Config.MainForm.SetStatusText("全部验证完成，耗时" + sb.ToString());
                    Config.MainForm.SetToolTipText("全部验证完成");
                    this.timerCheckAllTested.Stop();
                    this.timerCheckAllTested.Enabled = false;
                }
            }
            catch (Exception ex)
            {
                this.timerCheckAllTested.Stop();
                this.timerCheckAllTested.Enabled = false;
                MsgBox.ShowExceptionMessage(ex);
            }
        }

        private void tsmiUseIt_Click(object sender, EventArgs e)
        {
            try
            {
                proxyHelper.SetIEProxy(this.GetProxyInfo(), 1);
            }
            catch (Exception ex)
            {
                MsgBox.ShowExceptionMessage(ex);
            }
        }

        private void tsmiCancelProxy_Click(object sender, EventArgs e)
        {
            try
            {
                proxyHelper.SetIEProxy("", 0);
            }
            catch (Exception ex)
            {
                MsgBox.ShowExceptionMessage(ex);
            }
        }

        private void dgvProxyList_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            try
            {
                if (e.RowIndex == -1 && e.ColumnIndex == 4)
                {
                    // Check which column is selected, otherwise set NewColumn to null.
                    DataGridViewColumn newColumn = dgvProxyList.Columns[5];

                    DataGridViewColumn oldColumn = dgvProxyList.SortedColumn;
                    ListSortDirection direction;

                    // If oldColumn is null, then the DataGridView is not currently sorted.
                    if (oldColumn != null)
                    {
                        // Sort the same column again, reversing the SortOrder.
                        if (oldColumn == newColumn &&
                            dgvProxyList.SortOrder == SortOrder.Ascending)
                        {
                            direction = ListSortDirection.Descending;
                        }
                        else
                        {
                            // Sort a new column and remove the old SortGlyph.
                            direction = ListSortDirection.Ascending;
                            oldColumn.HeaderCell.SortGlyphDirection = SortOrder.None;
                        }
                    }
                    else
                    {
                        direction = ListSortDirection.Ascending;
                    }

                    // If no column has been selected, display an error dialog  box.
                    if (newColumn == null)
                    {
                        MsgBox.ShowMessage("Select a single column and try again.");
                    }
                    else
                    {
                        dgvProxyList.Sort(newColumn, direction);
                        newColumn.HeaderCell.SortGlyphDirection =
                            direction == ListSortDirection.Ascending ?
                            SortOrder.Ascending : SortOrder.Descending;
                        dgvProxyList.Refresh();
                    }

                }
            }
            catch (Exception ex)
            {
                MsgBox.ShowExceptionMessage(ex);
            }
        }

        private void frmProxy_Load(object sender, EventArgs e)
        {
            try
            {
                this.dgvProxyList.Columns[5].Visible = false;
            }
            catch (Exception ex)
            {
                MsgBox.ShowExceptionMessage(ex);
            }
        }

        private void tsmiDelete_Click(object sender, EventArgs e)
        {
            DeleteProxy();
        }

        private void tsmiClear_Click(object sender, EventArgs e)
        {
            if (DialogResult.Yes == MsgBox.ShowQuestionMessage("确定要清空列表中数据吗？"))
            {
                Config.ProxyData.Rows.Clear();
                BindDgv(Config.ProxyData);
            }
        }

        private void tsbSearch_Click(object sender, EventArgs e)
        {
            if (!Config.MainForm.tsslStatus.Text.Contains("正在验证"))
            {
                if (this.tstxtArea.Text.Trim() != "" || this.tstxtPort.Text.Trim() != "")
                {
                    DataView dv = new DataView(Config.ProxyData);
                    StringBuilder sbWhere = new StringBuilder("1=1 ");
                    if (this.tstxtArea.Text.Trim() != "")
                        sbWhere.Append(" and Area like '%" + this.tstxtArea.Text.Trim() + "%'");
                    if (this.tstxtPort.Text.Trim() != "")
                        sbWhere.Append(" and Port = '" + this.tstxtPort.Text.Trim() + "'");
                    dv.RowFilter = sbWhere.ToString();

                    this.BindDgv(dv.ToTable());
                }
                else
                {
                    this.BindDgv(Config.ProxyData);
                }
                Config.MainForm.tsslStatus.Text = "共" + this.dgvProxyList.RowCount + "条";
            }
        }

        #endregion

        #region Methods
        private void EnableThis()
        {
            this.dgvProxyList.Enabled = !this.dgvProxyList.Enabled;
        }

        private void BindDgv()
        {
            Config.MainForm.SetStatusText("正在读取数据...");
            proxyHelper = new ProxyHelper();
            if (Config.ReadDataTimes > 0)
            {
                Config.ProxyListUrl = Config.ProxyListUrlOld;
            }
            Config.ProxyData = proxyHelper.GetProxyList();
            DelegateVoid dv = new DelegateVoid(this.BindData);
            this.Invoke(dv);
            Config.ReadDataTimes++;
            if (Config.ProxyData.Rows.Count > 0)
            {
                Config.MainForm.SetStatusText("共" + Config.ProxyData.Rows.Count.ToString() + "条获取完毕");
            }
            else
            {
                Config.MainForm.SetStatusText("网络繁忙，请稍后再试！");
            }
            Config.MainForm.toolBtn_ReadData.Text = "读取数据";
            Config.MainForm.toolBtn_ReadData.Image = ProxyHero.Properties.Resources.run;
        }

        public void BindDgv(DataTable dt)
        {
            this.dgvProxyList.DataSource = dt;
            this.dgvProxyList.Refresh();
        }

        public void BindData()
        {
            this.dgvProxyList.DataSource = Config.ProxyData;
            this.dgvProxyList.Refresh();
        }

        /// <summary>
        /// 获取代理列表
        /// </summary>
        public void GetProxyList()
        {
            try
            {               
                DelegateVoid delegateBindData = new DelegateVoid(this.BindDgv);
                threadGetProxyList = new Thread(new ThreadStart(delegateBindData));
                threadGetProxyList.Start();
            }
            catch (Exception ex)
            {
                try
                {
                    Config.MainForm.SetStatusText(ex.Message);
                }
                catch
                { }
            }
            finally
            {
                //this.Invoke(delegateEnablePanel);
                //this.StopThread();
            }
        }

        /// <summary>
        /// 获取代理信息
        /// </summary>
        /// <returns></returns>
        private string GetProxyInfo()
        {
            int rowIndex = this.dgvProxyList.CurrentRow.Index;
            return this.dgvProxyList.Rows[rowIndex].Cells[0].Value.ToString() + ":" + this.dgvProxyList.Rows[rowIndex].Cells[1].Value.ToString();
        }

        /// <summary>
        /// 验证代理
        /// </summary>
        private void Test()
        {
            DelegateVoid delegateVoid = new DelegateVoid(this.EnableThis);
            this.Invoke(delegateVoid);

            Config.MainForm.SetStatusText("正在验证代理请稍后...");
            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
            sw.Start();
            ProxyEntity setting = this.GetProxySetting();
            DataRow[] drs = Config.ProxyData.Select("IP='" + setting.Ip + "' and Port ='" + setting.Port.ToString() + "'");
            drs[0]["TestTime"] = "正在验证...";

            try
            {
                TestEntity te = new TestEntity();
   
                #region 读取验证配置
                if (Config._localConfig == null)
                {
                    Config._localConfig = XmlHelper.XmlDeserialize(
                        Config.ConfigPath,
                        typeof(ConfigEntity)) as ConfigEntity;
                }

                if (Config._localConfig.DefaultTestUrl != null)
                {
                    te = Config._localConfig.DefaultTestUrl;
                }
                #endregion

                if ((bool)HttpHelper.TestProxy(setting, te)[0])
                {
                    sw.Stop();
                    Config.MainForm.SetStatusText("此代理有效！耗时：" + sw.ElapsedMilliseconds.ToString("F0") + "毫秒。");

                    drs[0]["TestTime"] = sw.ElapsedMilliseconds.ToString("F0") + "ms";
                    drs[0]["Speed"] = double.Parse(sw.ElapsedMilliseconds.ToString("F0"));
                    if (Config._localConfig.CheckAnonymous)
                    {
                        IpHelper ipHelper = new IpHelper(setting.IpAndPort);
                        drs[0]["Type"] = ipHelper.ProxyType;
                    }
                }
                else
                {
                    Config.MainForm.SetStatusText("此代理无效！");
                     drs[0]["TestTime"] = "无效";
                }
            }
            catch (Exception ex)
            {
                try
                {
                    drs[0]["TestTime"] = ex.Message;
                    Config.MainForm.SetStatusText(ex.Message);
                }
                catch (Exception)
                { }
            }

            this.Invoke(delegateVoid);
            //this.StopThread();
        }

        /// <summary>
        /// 验证全部
        /// </summary>
        /// <param name="settings"></param>
        private void TestAllList(object settings)
        {
            foreach (ProxyEntity setting in settings as List<ProxyEntity>)
            {
                System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                sw.Start();

                try
                {
                    TestEntity te = new TestEntity();

                    if (Config._localConfig.DefaultTestUrl != null)
                    {
                        te = Config._localConfig.DefaultTestUrl;
                    }
                    bool testResult = (bool)HttpHelper.TestProxy(setting, te)[0];
                    lock (Config.ProxyData)
                    {
                        DataRow[] drs = Config.ProxyData.Select("IP='" + setting.Ip + "' and Port ='" + setting.Port.ToString() + "'");
                        drs[0]["TestTime"] = "正在验证...";

                        if (testResult)
                        {
                            sw.Stop();
                            IpHelper ih = new IpHelper(setting.Ip);
                            if (Config._localConfig.CheckAnonymous)
                            {
                                IpHelper ipHelper = new IpHelper(setting.IpAndPort);
                                drs[0]["Type"] = ipHelper.ProxyType;
                            }
                            drs[0]["Area"] = ih.Location;
                            drs[0]["TestTime"] = sw.ElapsedMilliseconds.ToString("F0") + "ms";
                            drs[0]["Speed"] = double.Parse(sw.ElapsedMilliseconds.ToString("F0"));

                            DelegateAddToAvaliableProxy daap = new DelegateAddToAvaliableProxy(this.AddToAvaliableProxy);
                            this.Invoke(daap, new object[] { setting.Ip, setting.Port, double.Parse(sw.ElapsedMilliseconds.ToString("F0")) });
                        }
                        else
                        {
                            drs[0]["TestTime"] = "无效";
                            drs[0]["Speed"] = 888888;
                        }
                    }
                }
                catch (Exception ex)
                {
                    try
                    {
                        lock (Config.ProxyData)
                        {
                            DataRow[] drs = Config.ProxyData.Select("IP='" + setting.Ip + "' and Port ='" + setting.Port.ToString() + "'");
                            drs[0]["TestTime"] = ex.Message;
                            drs[0]["Speed"] = 888888;
                        }
                    }
                    catch (Exception exx)
                    {
                        TxtHelper.WriteLog(exx.Message);
                    }
                }
                finally
                {
                    testAll[setting.Id] = true;
                }
            }
        }

        private void AddToAvaliableProxy(object Ip, object Port, object speed)
        {
            if (!Config.AvailableProxyData.Rows.Contains(new object[] { Ip, Port }))
            {
                Config.AvailableProxyData.Rows.Add(new object[] { Ip, Port, null, "HTTP", "", speed });
            }
        }

        /// <summary>
        /// 获取代理设置
        /// </summary>
        /// <returns></returns>
        public ProxyEntity GetProxySetting()
        {
            try
            {
                ProxyEntity setting = new ProxyEntity();

                if (this.strIP != "")
                {
                    setting.Ip = this.strIP;
                }
                if (this.strPort != "")
                {
                    setting.Port = int.Parse(this.strPort);
                }

                setting.ProxyType = 2;
                setting.UserName = string.Empty;
                setting.Password = string.Empty;
                return setting;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 关闭线程
        /// </summary>
        public void StopThread()
        {
            if (this.threadGetProxyList != null && this.threadGetProxyList.IsAlive)
            {
                this.threadGetProxyList.Abort();
                this.threadGetProxyList.Join();
                this.threadGetProxyList = null;
            }

            if (this.threadTest != null && this.threadGetProxyList.IsAlive)
            {
                this.threadTest.Abort();
                this.threadTest.Join();
                this.threadTest = null;
            }
        }

        /// <summary>
        /// 验证全部代理
        /// </summary>
        public void TestAll()
        {
            try
            {
                #region Test
                if (Config.ProxyData.Rows.Count > 0)
                {
                    swTestAll = new Stopwatch();
                    swTestAll.Start();
                    int intEvery = Config.ProxyData.Rows.Count / Config.LocalConfig.TestThreadsCount; //得到每组个数
                    
                    testAll = new bool[Config.ProxyData.Rows.Count];
                    Config.MainForm.SetStatusText("正在验证...");
                    this.tsmiTest.Enabled = false;
                    this.tsmiClear.Enabled = false;
                    this.tsmiDelete.Enabled = false;
                    this.timerCheckAllTested.Enabled = true;
                    this.timerCheckAllTested.Start();
                    int therdCount = Config.LocalConfig.TestThreadsCount;
                    therdCount = intEvery == 0 ? Config.ProxyData.Rows.Count : therdCount; //如果验证数量小于线程数
                    if (intEvery == 0)
                        intEvery = 1;
                    theads = new Thread[therdCount];

                    for (int i = 0; i < therdCount; i++)
                    {
                        if (intEvery * therdCount <= Config.ProxyData.Rows.Count)
                        {
                            List<ProxyEntity> pList = new List<ProxyEntity>();

                            int k = intEvery * (i + 1);

                            // 如果最后一个线程的数量多出来了
                            if (i == therdCount - 1 &&
                                ((intEvery * therdCount) < Config.ProxyData.Rows.Count))
                            {
                                k = Config.ProxyData.Rows.Count;
                            }

                            for (int j = i * intEvery; j < k; j++)
                            {
                                ProxyEntity pse = new ProxyEntity();
                                pse.Ip = Config.ProxyData.Rows[j]["IP"].ToString();
                                pse.Port = int.Parse(Config.ProxyData.Rows[j]["Port"].ToString());
                                pse.Id = j;
                                //Config.ProxyData.Rows[j]["TestTime"] = "正在验证...";
                                testAll[j] = false;
                                pList.Add(pse);
                            }

                            if (pList.Count > 0)
                            {
                                DelegateTestAll d = new DelegateTestAll(this.TestAllList);
                                theads[i] = new Thread(new ParameterizedThreadStart(d));
                                theads[i].Start(pList);
                            }
                        }
                    }
                }
                #endregion
            }
            catch
            {
                StopAll();
                throw;
            }
        }

        public void StopAll()
        {
            Config.MainForm.SetStatusText("正在停止验证...");
            if (this.theads != null && this.theads.Length > 0)
            {
                for (int i = 0; i < this.theads.Length; i++)
                {
                    if (theads[i] != null && theads[i].IsAlive)
                    {
                        Config.MainForm.SetStatusText("正在终止线程" + (i + 1) + "...");
                        this.theads[i].Abort();
                        this.theads[i].Join();
                        this.theads[i] = null;
                    }
                }
            }
           // StopThread();

            this.timerCheckAllTested.Stop();
            this.timerCheckAllTested.Enabled = false;
            this.dgvProxyList.Enabled = true;
            this.tsmiTest.Enabled = true;
            Config.MainForm.SetStatusText("就绪");
        }

        /// <summary>
        /// 删除代理
        /// </summary>
        public void DeleteProxy()
        {
            ProxyEntity setting = this.GetProxySetting();
            DataRow[] drs = Config.ProxyData.Select("IP='" + setting.Ip + "' and Port ='" + setting.Port.ToString() + "'");
            if (drs.Length > 0)
            {
                lock (Config.ProxyData)
                {
                    Config.ProxyData.Rows.Remove(drs[0]);
                }
                BindDgv(Config.ProxyData);
                this.strIP = "";
                this.strPort = "";
            }
        }
        #endregion
    }
}
